/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package provaserializzazione;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.*;
import java.util.*;
import java.sql.*;
/**
 * Classe principale per la fase di apprendimento
 * @author Francesco
 */
public class Provaserializzazione {

    /**
     * Main che da' il via alla fase di apprendimento
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        System.out.println("Acquisco Dati Utente");
        //creaUtenti("gender.dat");
        System.out.println("Acquisco Dati Votazioni");
        //acquisisciVoti("trainingRatings.dat");
        
        //determina similarità
        trovaSimilarita("gender.dat");
        
        /**
        Utente due = retriveUtente(1);
        Map<Integer, Double> mappa1 = due.getVotiUtente();
        Set<Integer> set1 = mappa1.keySet();
        System.out.println(set1);
        //System.out.println(mappa1.get(193687));
        
        Utente ventisei = retriveUtente(47082);
        Map<Integer, Double> mappa2 = ventisei.getVotiUtente();
        Set<Integer> set2 = mappa2.keySet();
        System.out.println(set2);
        //System.out.println(mappa1.get(193687));
        
        Set intersezione = trovaIntesezione(set1, set2);
        System.out.println(intersezione);
        **/
        
        
        
        //scrivi su file i dati della tabella similarita
        //Utilita.loadDriver();
        //Utilita.doConnection("localhost", "3306", "prova", "root", "");
        //ResultSet resultset = Utilita.getTable();
        //scriviTabellaFile(resultset);
        //Utilita.closeConnection();
        
        
    }

    /**
     * Metodo che crea un file per ogni utente
     * @param s il path del file contenente l'elenco degli utenti ed il loro sesso
     */
    public static void creaUtenti(String s){
        //apro il file degli utenti
        try{
        FileReader r = new FileReader(s);
        Scanner in = new Scanner(r);
        while(in.hasNextLine()){
            String line = in.nextLine();
            StringTokenizer st = new StringTokenizer(line,",");                
            int idutente = Integer.parseInt(st.nextToken());
            char sesso = st.nextToken().charAt(0);
            Utente u = new Utente(idutente, sesso);
            u.salvaUtente();
        }//fine while che scorre il file utenti
        
        in.close();
        r.close();
        
        }catch(IOException exception){
            System.out.println("Errore processamento file" + exception);
        }/*fine catch*/
    }/*fine metodo creaUtenti*/
    
    
   /**
    * Metodo che riempie i file degli utenti con le loro interazioni
    * @param s il path del file contenente l'elenco delle interazioni (voti) degli utenti
    */
    public static void acquisisciVoti(String s){
        //apro il file degli utenti
        try{
        FileReader r = new FileReader(s);
        Scanner in = new Scanner(r);
        while(in.hasNextLine()){
            String line = in.nextLine();
            StringTokenizer st = new StringTokenizer(line,",");
            int userid = Integer.parseInt(st.nextToken());
            int profiloid = Integer.parseInt(st.nextToken());
            double d = Double.parseDouble(st.nextToken());
            Utente u = retriveUtente(userid);
            //richiamare la funzione getUtente e poi inserisciVoto
            u.inserisciVoto(profiloid, d);
            u.salvaUtente(); //salvo l'utente
        }//fine while che scorre il file utenti
        
        in.close();
        r.close();
        
        }catch(IOException exception){
            System.out.println("Errore processamento file" + exception);
        }/*fine catch*/
    }
    
    /**
     * Metodo che deserializza (reucpera) un utente
     * @param i l'id dell'uente da recuperare
     */
    public static Utente retriveUtente(int i){
        try{
        String percorso = i + ".dat";
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(percorso));
        Utente u = (Utente) in.readObject();
        in.close();
        return u;
        
        }catch(IOException exception){
           System.out.println("Errore processamento file" + exception); 
        }
        catch(ClassNotFoundException exception){
           System.out.println("Errore processamento file" + exception); 
        }
            
            
       return null;     
    }
    
    
    /**
     * Metodo che ricava la similarità tra gli utenti e la salva in un file cvs
     * @param s il path del file contenente l'elenco degli utenti ed il loro sesso
     */
    public static void trovaSimilarita(String s){
        //apro il file degli utenti
        try{
            
            
            //scrivo dati su file
            FileOutputStream prova = new FileOutputStream("sim.dat");
            PrintStream scrivi = new PrintStream(prova);
            //fine scrivo dati file
            
            
            for(int i=1 ; i<=135359; i++){
                
                //recupero le info di questo utente
                Utente u1 = retriveUtente(i);
                Map<Integer, Double> mappa1 = u1.getVotiUtente();
                Set<Integer> set1 = mappa1.keySet();
                
                //controllo se utente uno e vuoto, se vuoto non serve fare nulla
                if(u1.getNumVoti() != 0){  
                
                
                
                    for(int j=i+1 ; j<=135359; j++){
                        //recupero info utente u2
                        Utente u2 = retriveUtente(j); 
                        //controllo se l'utente2 è vuoto
                        if(u2.getNumVoti() != 0){
                            
                            
                            
                            //devo verificare se ci sono intersezioni nelle chiavi-> significa 
                            //che hanno votato elementi in comune
                            Map<Integer, Double> mappa2 = u2.getVotiUtente();
                            Set<Integer> set2 = mappa2.keySet();
                            Set intersezione = trovaIntesezione(set1, set2);
                            if( (intersezione.size() != 0) && (intersezione.size() > 8)){
                                //ci sono elementi votati in comune (di cui conosco le chiavi) e posso calcolare la similarita
                                double media1 = u1.getMedia();
                                double media2 = u2.getMedia();
                                double num = 0;
                                double sq1 = 0;
                                double sq2 = 0;
                                //Implementazione Formula similarità di Pearson
                                //prodotto al numeratore 
                                Iterator<Integer> iter = intersezione.iterator();
                                while(iter.hasNext()){
                                    int y = iter.next();
                                    double a = mappa1.get(y) - media1;
                                    double b = mappa2.get(y) - media2;
                                
                                    num = num + (a * b);
                                
                                    sq1 = sq1 + (a*a);
                                    sq2 = sq2 + (b*b);
                                
                                
                                }   
                            
                                sq1 = Math.sqrt(sq1);
                                sq2 = Math.sqrt(sq2);
                                double den = sq1 * sq2; 
                            
                            
                                double sim = num/den;
                            
                                //System.out.println("La similarita tra " + u1.getId() + " e " + u2.getId() + " e' " + sim);
                                if(Math.abs(sim) > 0.2){
                                scrivi.println(u1.getId() + "," + u2.getId() + "," + sim);
                                }
                            
                            
                            
                            }//fine if che controlla intesezione.size() != 0
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                        }/*fine if controllou2 vuoto*/
                        
                        
                        
                    }/*fine secondo for*/
                
                
                }/*fine if controllo vuoto utente1*/
                
                
                
            }/*fine primo for*/
            
            
            
            
            
            scrivi.close();
            prova.close();
            
            
        }catch(IOException exception){
            System.out.println("Errore processamento file" + exception);
        }//fine catc
    }//fine metodo trovaSimilarita
    
    
    
    /**
     * Metodo che trova l'intersezione tra due insiemi per vedere se due utenti hanno effettuato delle votazioni in comune
     * @param s1 primo insieme di interi
     * @param s2 secondo insieme di interi
     */
    public static Set<Integer> trovaIntesezione(Set<Integer> s1, Set<Integer> s2){
        Set<Integer> ris = new HashSet<Integer>();
        //itero sugli elementi del primo insieme e vedo se sono presenti nel secondo insieme
        //gli elementi in comune li metto nell'insieme "ris"
        Iterator<Integer> iter = s1.iterator();
        while(iter.hasNext()){
            int e = iter.next();
            if(s2.contains(e)){
                ris.add(e);
            }//fine if
                
        }//fine while
        return ris;
    }//fine metodo trovaIntersezione
    
    
    
    /**
     * Metodo scrive su file i dati ricavati da una interrogazione su db
     * @param res il risultato della query    
     */
    public static void scriviTabellaFile(ResultSet res){
        try{
            FileOutputStream prova = new FileOutputStream("datiDB.dat");
            PrintStream scrivi = new PrintStream(prova);
            while(res.next()){
                String a = res.getString("idutente");
                String b = res.getString("idvotato");
                Double c = res.getDouble("valore");
                scrivi.println(a + "," + b + "," + c);
            }/*fine while*/
            scrivi.close();
            prova.close();
        }catch(IOException e){
            e.printStackTrace();
        }/*fine catch*/
        catch(SQLException e){
            e.printStackTrace();
        }/*fine catch*/
    }/*fine metodo scriviTabellaFile*/
    
    
    
    
    
    


}

